package com.hcj.springcloud.MyThreadExample.Lock;

import lombok.Data;

import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by xxx on 2016/3/20.
 */
public class LockTest {

    public static void init() {
        final Outprint outprint = new Outprint();
        new Thread(new Runnable() {
            public void run() {
                try {
                    while (true) {
                        Thread.sleep(2000);
                        outprint.out("hadoop");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        ).start();


        new Thread(new Runnable() {
            public void run() {
                try {
                    while (true) {
                        Thread.sleep(2000);
                        outprint.out("spark");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        ).start();
    }

    static class Outprint {
        Lock lock = new ReentrantLock();

        public void out(String str) {
            lock.lock();
            try {
                for (int i = 0; i < str.length(); i++) {
                    System.out.print(str.charAt(i));
                }
                System.out.println();
                // lock.unlock();//释放锁（如果上面的代码在unlock之前出错，那么锁将不会被释放，所以最好放到finally中）
            } finally {
                lock.unlock();//释放锁
            }
        }
    }


    /**
     * 死锁的demo
     */
    public static void testDeadLock() {
        final Object A = new Object();
        final Object B = new Object();
        Thread threadA = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        System.out.println("threadA get objA");
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 对象A锁释放
//                    try {
//                        A.wait(1000L);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }

                    synchronized (B) {
                        System.out.println("threadA get objB");
                    }
                }
            }
        });

        Thread threadB = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B) {
                    try {
                        System.out.println("threadB get objB");
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    // 对象B锁释放
//                    try {
//                        B.wait(1000L);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
                    synchronized (A) {
                        System.out.println("threadB get objA");
                    }
                }
            }
        });

        threadA.start();
        threadB.start();
    }

    @Data
    static class TestOptional {
        private Optional<String> id;
        private Optional<String> name;
        private Optional<Instant> instant;
    }

    public static void main(String[] args) {
//        LockTest.init();
        // jdk8的新特性
        System.out.println(Instant.now().atZone(ZoneId.systemDefault()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        //testDeadLock();


        // 测试jdk8中的optional
        TestOptional testOptional = new TestOptional();
        testOptional.setId(Optional.of(null));
        testOptional.setName(Optional.of(""));
        testOptional.setInstant(Optional.of(null));
    }
}
